from mosaic import *
OS2023(10)
Changelog & 反馈
背景回顾:我们分析了同步的本质需求:两个并发的线程等待某个同步条件达成,完成时间线的 “交汇”。相应地,我们有了条件变量实现同步,并且解决了生产者-消费者问题 (括号打印问题)。
本讲内容:另一种共享内存系统中常用的同步方法:信号量 (E. W. Dijkstra)
slideshow('10.1')
demo('pc-sem', 'c/pc-sem.c', libs=['thread.h', 'thread-sync.h'])
model('m/pc-sem.py', check=True)
slideshow('10.2')
demo('join-sem', 'c/join-sem.c', libs=['thread.h', 'thread-sync.h'])
demo('fish-sem', 'c/fish-sem.c', libs=['thread.h', 'thread-sync.h'])
slideshow('10.3')
demo('pc-sem', 'c/philosopher.c', libs=['thread.h', 'thread-sync.h'])
信号量是一种特殊的条件变量,而且可以在操作系统上被高效地实现,避免 broadcast 唤醒的浪费:
void P() {
WAIT_UNTIL(count > 0) {
count--;
}
}
void V() {
count++;
}
同时,我们也可以把信号量理解成袋子里的球,或是管理游泳池的手环,因此它在符合这个抽象时,能够带来优雅的代码。
更重要的是,但凡我们能将任务很好地分解成少量串行的部分和绝大部分 “线程局部” 的计算,那么生产者-消费者和计算图模型就能实现有效的并行。精心设计的分布式同步协议不仅可能存在正确性漏洞,带来的性能收益很可能也是微乎其微的。
教科书 Operating Systems: Three Easy Pieces:
运行示例代码并观察执行结果,有兴趣的同学可以试着用信号量实现条件变量——当然,仅仅有一个实现是不够的,你应当尽可能地压力测试它。